﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows.Forms;
using System.Threading;  //usado para administrar los hilos
using System.Collections;  //usado para ArrayList

using SistemaCenterQuimPost.Plantillas; //usado para hacer referencias a la fecha;
using SistemaCenterQuimPost.Reportes; //usado para imprimir la venta.
using SistemaCenterQuimPost.Entidad;  //Usado para instanciar objetos de clase Producto y agilizar el filtrado de descripción.
using System.Text.RegularExpressions; //usado para expresiones regulares. Filtrar descripciones
using SistemaCenterQuimPost.Control; //usado para validar datos.


namespace SistemaCenterQuimCentral.UI.CentralSupervisor
{
    public partial class frmRecibirProductosCentral : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {
        //----------ATRIBUTOS----------------
        private DataSet3 centerQuimDs;
        private DataSet3TableAdapters.ProductosTableAdapter productosTa;
        private DataSet3TableAdapters.IngresoMercaderiaTableAdapter ingresoMercaderiaTa;
        private DataSet3TableAdapters.ProductosxIngresoMercaderiasTableAdapter productoxIngresoTa;
        private DataSet3TableAdapters.MovimientosxProductosTableAdapter movimientosTa;

        private DsProveedoresCentral proveedoresDs;
        private DsProveedoresCentralTableAdapters.ProveedoresTableAdapter proveedoresTa;

        

        private bool refrescarResgProductos; //La primera vez debe refrescar el resgProductos.

        private ArrayList resgProductos; // colección usada para guardar Codigos de productos y descripción, se tiene una pequeña base de dato para realizar las busqueda mediante filtros más rapidamente.

        private Thread oHiloActualizarResgProductos; //hilos que son ejecutados concurrentemente con la aplicación.
        private Thread oHiloFiltrarDescripcion;

        private string estadoDelFormulario;




        //---------CONSTRUCTORES------------
        public frmRecibirProductosCentral()
        {
            InitializeComponent();

            centerQuimDs = new DataSet3();
            productosTa = new DataSet3TableAdapters.ProductosTableAdapter();
            ingresoMercaderiaTa = new DataSet3TableAdapters.IngresoMercaderiaTableAdapter();

            productoxIngresoTa = new DataSet3TableAdapters.ProductosxIngresoMercaderiasTableAdapter();
            movimientosTa = new DataSet3TableAdapters.MovimientosxProductosTableAdapter();

            proveedoresDs = new DsProveedoresCentral();
            proveedoresTa = new DsProveedoresCentralTableAdapters.ProveedoresTableAdapter();

            estadoDelFormulario = "";

            refrescarResgProductos = true; //inicializamos a true, ya que la primera vez que trate de usar ResgProductos tendra que actualizar.

            this.resgProductos = new ArrayList();  //se inicializa la colección ArrayList que guardará una base de datos parcial.          

            this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos)); //Instancia el hilo y lo delega al metodo actualizarResgProductos. 
            this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion));

        }


        //--------ESTADOS-------------------
        private void frmRecibirProductosCentral_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;  //necesario para trabajar con hilos.
            
            this.limpiarDatos(); //deja la preparada para nuevos datos.

            obtenerProveedores(); //carga en el cboProveedores, los proveedores disponibles en base de dato
            

            estEsperandoOperacion(); //estado al comenzar el formulario o al fracasar en la busqueda.
        }

        //virtual me permite redefinir, en este caso solo en las clases hijas
        protected virtual void estEsperandoOperacion() //estado luego de realizar una busqueda exitosa, agregar o editar. Es decir con datos en vista.
        {

            System.Windows.Forms.Control[] controlesHabilitados = { this.txtCodBarra, this.btnBusCodigo, this.txtDescripcion, this.btnBusDescripcion };
            System.Windows.Forms.Control[] controlesDeshabilitados = { this.lstProductosCodBarra, this.lstProductosDescripcion };
            System.Windows.Forms.Control[] controlesVisibles = { };
            System.Windows.Forms.Control[] controlesInvisibles = { this.lstProductosCodBarra, this.lstProductosDescripcion, lblError };

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            if (refrescarResgProductos) //si hace falta actualizar el refrescarResgProducto se realiza
            {
                ejecutarHiloActualizarResgProductos();

            }

            
            errorProvider1.Clear();  //se borran los errores, si habian.

            txtCodBarra.Focus();   //se deja el foco en txtCodBarra

            estadoDelFormulario = "estEsperandoOperacion";


        }


        //----------METODOS VARIOS-------------
        private void limpiarDatos() //deja el formulario preparado para ingresar nuevos datos.
        {

            this.cboProveedor.Text = "";
            this.dtpFecha.Text = "";
            this.txtNumeroRemito.Text = "";
            this.cboTurno.Text = "";
            
            this.txtCodBarra.Text = "";
            this.txtDescripcion.Text = "";
            this.dgvProductos.Rows.Clear();

        }

        private void obtenerProveedores() //carga en el cboProveedores los proveedores en base de datos
        {
            try
            {
                this.cboProveedor.Items.Clear(); //todo lo que tenía antes. 

                proveedoresTa.FillByVigente(proveedoresDs.Proveedores);

                foreach (DataRow unaFila in proveedoresDs.Proveedores) //Se recorre todas las filas  del centerQuimDs.Proveedores y se cargan al cboProveedores
                {
                    this.cboProveedor.Items.Add(Convert.ToString(unaFila[1]));
                }

            }

            catch (IndexOutOfRangeException)
            {
                //Si se produce esta excepción no se tiene en cuenta ya que podría no tener proveedores.
            }

            catch (Exception ex)
            {

                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        //Virtual, permite redefinir en frmAltaProductosDisueltos y frmRecibirProductos
        private void actualizarResgProductos() //Se refresca el arrayList resgProductos
        {
            try
            {
                //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,...);
                productosTa.FillByNoGranel(centerQuimDs.Productos);

                resgProductos.Clear(); //Se vacia resgProductos (ArrayList)

                foreach (DataRow unaFila in centerQuimDs.Productos) //Se recorre todas las filas  del centerQuimDs.Productos y se cargan los productos al ArrayList
                {
                   resgProductos.Add(new Producto(Convert.ToString(unaFila[0]), Convert.ToString(unaFila[3])));
                    
                }

                refrescarResgProductos = false;

            }
            catch (IndexOutOfRangeException)
            {
                //si llega a ocurrir esta excepcion no se tiene en cuenta. Podría no haber productos cargados y lanzaría esta excepción.

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }

        }

        protected void btnBusCodigo_Click(object sender, EventArgs e)  //método que se ejecuta cuando se presiona sobre el botón btnBusCodigo
        {
            eventoBusCodigo();

        }

        protected virtual void eventoBusCodigo()  //Se encapsula en un método para que pueda usar cuando se presiona Enter sobre el txtCodBarra en estado de busqueda o click en btnBusCodBarra.
        {

            //no hace falta que pregunte si txtCodBarra es blanco, ya que por la forma de filtrar no encontrará nada igual.                                

            if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
            {
                ejecutarHiloActualizarResgProductos();  //ejecuta el hilo que actualiza el ResgProductos
            }

            filtrarCodigoBarra();


            if (lstProductosCodBarra.Items.Count == 0)  //el filtro no obtuvo coincidencias.
            {
                //Se informa que no se encontró nada 
                MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                //Como no encontró nada se deja en este estado.
                this.estEsperandoOperacion();
            }
            else
            {
                if (lstProductosCodBarra.Items.Count == 1)   //solo se encontró una sola coincidencia. No es necesario mostrar el lstProductosCodBarra. Directamente se muestra el producto.
                {
                    this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                    cargarProductoPorCodigo(this.txtCodBarra.Text.Trim());  //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.

                    estEsperandoOperacion(); //se deja en el estado necesario

                }
                else
                {
                    //si se obtuvo más de una coincidencia, solo se muestran éstas en lstProductosCodBarra, y espera a que el usuario seleccione una.

                    lstProductosCodBarra.Visible = true;
                    lstProductosCodBarra.Enabled = true;

                    //lstProductosCodBarra.Focus(); //se deja el foco en el dgvProductosCodBarra para que elija alguna coincidencia.

                    //lstProductosCodBarra.SelectedIndex=0;  //se deja seleccionado el primer items.
                }

            }

        }

        protected void ejecutarHiloActualizarResgProductos() // hilo para actualizar el atributo ResgProductos
        {
            if ((oHiloActualizarResgProductos.ThreadState == ThreadState.Unstarted) || (oHiloActualizarResgProductos.ThreadState == ThreadState.Stopped))
            {
                this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos));
                this.oHiloActualizarResgProductos.Priority = ThreadPriority.Highest;
                this.oHiloActualizarResgProductos.Start();  //Se ejecuta el hilo para actualizar el atributo ResgProductos
            }
        }



        protected virtual void cargarProductoPorCodigo(string unCodBarra) //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.
        {
            try
            {
                //(ALE)HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,unCodBarra);
                productosTa.FillByCodigo(centerQuimDs.Productos, unCodBarra);

                //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
                dgvProductos.Rows.Add(centerQuimDs.Productos[0].codProducto, centerQuimDs.Productos[0].descripcion, 0); //se carga un nuevo producto para recibir


                //...
                //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected void filtrarCodigoBarra()  //Filtra y carga las descripciones (si las hay) en el lstProductos. Método que se ejecuta dentro de un hilo. 
        {

            this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosCodBarra.Items.Clear(); //vaciamos el lstProductosCodBarra por si tuviera descripciones anteriores.


            foreach (Producto unProducto in resgProductos) //buscamos las descripciones asociadas al código y la cargamos en el lstProductosCodBarra
            {
                if (this.txtCodBarra.Text.Trim() == unProducto.CodBarra)
                {
                    lstProductosCodBarra.Items.Add(unProducto.Descripcion);
                }

            }

        }

        protected void lstProductosCodBarra_DoubleClick(object sender, EventArgs e)  //captura en evento doble click sobre lstProductosCodBarra
        {
            procesarEleccionLstProductosCodBarra();
        }

        protected void procesarEleccionLstProductosCodBarra()  //se encapsulo para que se pueda usar con DoubleClick y Enter sobre el lstProductosCodBarra
        {
            try
            {
                this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                cargarProductoPorDescripcion(lstProductosCodBarra.SelectedItem.ToString()); //busca producto por descripción en la base de datos, y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected virtual void cargarProductoPorDescripcion(string unaDescripcion)  //busca el producto por descripción en la base de datos y lo carga en los textbox.
        {
            //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
            productosTa.FillByNombre(centerQuimDs.Productos, unaDescripcion);

            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
            dgvProductos.Rows.Add(centerQuimDs.Productos[0].codProducto, centerQuimDs.Productos[0].descripcion, 0); //se carga un nuevo producto para recibir
            //..
            //...
            //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

        }

        protected void txtCodBarra_KeyDown(object sender, KeyEventArgs e)  //captura el evento KeyDown sobre el txtCodBarra.
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (estadoDelFormulario == "estEsperandoOperacion") //estado esperando operación o estado inicial
                {
                    eventoBusCodigo();

                }

            }
            else
            {
                if ((e.KeyCode == Keys.Down) & (lstProductosCodBarra.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
                {

                    lstProductosCodBarra.SetSelected(0, true); //se deja seleccionado el primer items
                    lstProductosCodBarra.Focus(); //Se deja el foco sobre este control para que seleccione un items.
                }
            }

        }

        protected void lstProductosCodBarra_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosCodBarra cuando el control pierde el foco.
        {
            this.lstProductosCodBarra.Enabled = false;
            this.lstProductosCodBarra.Visible = false;
            this.lstProductosCodBarra.Items.Clear();
        }



        protected void txtDescripcion_TextChanged(object sender, EventArgs e) //evento que se desencadena cuando cambia el valor del TextBox
        {
            if (this.estadoDelFormulario == "estEsperandoOperacion") //el proceso es capturado solo si está en este estado.
            {
                eventoBusDescripcion();
            }

        }

        protected void eventoBusDescripcion()
        {
            if (txtDescripcion.Text != "") //Si txtDescripcion es distinto de blanco se realiza el procesamiento. Esto se realiza para no perder el tiempo en filtro innecesarios.
            {
                if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
                {
                    ejecutarHiloActualizarResgProductos();
                }

                ejecutarHiloFiltrarDescripcion();

                if (lstProductosDescripcion.Items.Count == 0)  //el filtro no obtuvo coincidencias, no se muestra el lstProductosDescripcion
                {
                    lstProductosDescripcion.Visible = false;
                    lstProductosDescripcion.Enabled = false;

                }
                else
                {
                    lstProductosDescripcion.Visible = true; //si se obtuvo una o más coincidencia se muestran en lstProductosDescripcion, y espera a que el usuario seleccione una.
                    lstProductosDescripcion.Enabled = true;

                }

            }
            else  //Si txtDescripcion es blanco no se realiza el procesamiento
            {
                lstProductosDescripcion.Enabled = false;
                lstProductosDescripcion.Visible = false;
            }
        }

        protected void ejecutarHiloFiltrarDescripcion()
        {
            if ((this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Unstarted) || (this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Stopped))
            {
                this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion)); //Instancia el hilo y lo delega al metodo filtrarDescripcion. 
                this.oHiloFiltrarDescripcion.Priority = ThreadPriority.AboveNormal;
                this.oHiloFiltrarDescripcion.Start();  //hilo que filtra las descripciones asociadas al valor del txtDescripcion y lo carga en lstProductosDescripcion
            }

        }


        protected void filtrarDescripcion()
        {
            //this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosDescripcion.Items.Clear(); //vaciamos el lstProductosDescripcion por si tuviera descripciones anteriores.

            try
            {
                foreach (Producto unProducto in resgProductos) //buscamos las descripciones que coinciden con (al menos una palabra o letra + txtDescripcion.text + ninguna o muchas palabras o letras) y la cargamos en el lstProductosDescripcion
                {

                    if (Regex.Match(unProducto.Descripcion, txtDescripcion.Text.Trim().ToUpper()).Success)
                    {
                        lstProductosDescripcion.Items.Add(unProducto.Descripcion);
                    }

                }
            }
            catch (InvalidExpressionException)
            {

            }

            catch (Exception)
            {
                txtDescripcion.Text = "";

            }

        }

        protected void txtDescripcion_KeyDown(object sender, KeyEventArgs e) //Método que captura el evento de presión de una tecla sobre txtDescripcion
        {
            if ((e.KeyCode == Keys.Down) & (lstProductosDescripcion.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
            {

                lstProductosDescripcion.SetSelected(0, true); //se deja seleccionado el primer items
                lstProductosDescripcion.Focus(); //Se deja el foco sobre este control para que seleccione un items.

            }

        }



        protected void lstProductosDescripcion_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosDescripcion cuando el control pierde el foco.
        {
            this.lstProductosDescripcion.Enabled = false;
            this.lstProductosDescripcion.Visible = false;
        }

        protected void lstProductosDescripcion_DoubleClick(object sender, EventArgs e) //evento que captura la elección de un item en el lstProductosDescripcion
        {
            procesarEleccionLstProductosDescripcion();
        }


        protected void procesarEleccionLstProductosDescripcion()  //Se encapsula para que capture Double click y Enter sobre  lstProductosDescripcion
        {
            try
            {
                this.estadoDelFormulario = "Buscando";

                cargarProductoPorDescripcion(lstProductosDescripcion.SelectedItem.ToString()); //busca producto por descripción y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected void btnBusDescripcion_Click(object sender, EventArgs e) //captura el evento Click sobre el boton btnBusDescripcion
        {
            eventoBusDescripcion();
        }

        protected void lstProductosCodBarra_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosCodBarra
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosCodBarra();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosCodBarra.SelectedIndex == 0))//si llega al primer lugar y presiona para arriba, vuelve al txtCodBarra
                {
                    txtCodBarra.Focus();
                }
            }
        }

        protected void lstProductosDescripcion_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosDescripcion
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosDescripcion();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosDescripcion.SelectedIndex == 0)) //si llega al primer lugar y presiona para arriba, vuelve al txtDescripcion
                {
                    txtDescripcion.Focus();
                }

            }
        }


        private void txtCodBarra_TextChanged(object sender, EventArgs e)  //si se modifica txtCodBarra, se oculta lstCodBarra
        {
            lstProductosCodBarra.Visible = false;
            lstProductosCodBarra.Enabled = false;
        }

        protected virtual void frmActualizarPreciosCentral_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F1)
            {

                bool tieneError = false;

                foreach (System.Windows.Forms.Control ctrl in this.Controls)
                {
                    if (errorProvider1.GetError(ctrl) != "")
                    {
                        tieneError = true;
                    }
                }

                if (tieneError) mostrarErrores();
            }
            else
            {
                if (e.KeyCode == Keys.F12)
                {
                    refrescarResgProductos = true;

                }
            }
        }

        private void btnProcesar_Click(object sender, EventArgs e)
        {
            procesar();
        }


        //Redefinido del padre
        protected void procesar() //se encapsulo en un método para usar cuando se presiona Enter con los textBox
        {
            if (formularioValido())
            {
                try
                {

                    DialogResult result = MessageBox.Show("¿Está seguro en recibir las unidades de los productos especificados en la grilla? ", "CONFIRMACION RECIPCIÓN DE UNIDADES DISUELTAS", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (result == DialogResult.Yes)
                    {
                        agregarIngreso();  //agrega un registro de remito a la tabla de Remito

                        agregarProductoXIngreso(); //agrega un registro de productosXRemito a esa tabla

                        incrementarStockProductos(); //incrementa el stock del producto ingresado.

                        //Se muestra un mje de confirmación.
                        MessageBox.Show("Productos ingresados con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                        limpiarDatos();

                        estEsperandoOperacion();
                    }

                }
                catch (IndexOutOfRangeException)
                {

                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error en estado agregar 
                    this.Close();
                }

            }
            else
            {
                informarExistenciaError();
            }


        }

        //redefinido del padre
        protected virtual bool formularioValido()
        {

            validarProveedor();

            validarTurno();

            validarGrilla();

            validarNumeroRemito();


            if ((errorProvider1.GetError(cboProveedor) == "") & (errorProvider1.GetError(txtNumeroRemito) == "") & (errorProvider1.GetError(dgvProductos) == "") & (errorProvider1.GetError(cboTurno) == ""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void validarProveedor()
        {
            if (cboProveedor.Text.Trim() == "")
            {
                errorProvider1.SetError(cboProveedor, "Proveedor: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(cboProveedor, "");
            }
        }

        private void validarNumeroRemito()
        {
            if (txtNumeroRemito.Text.Trim() == "")
            {
                errorProvider1.SetError(txtNumeroRemito, "N° Remito: el campo se encuentra vacio\n\n");
            }
            else
            {

                errorProvider1.SetError(txtNumeroRemito, new ValidarDatos().validarLongitud("N° Remito:", txtNumeroRemito.Text, 30));

                if ((errorProvider1.GetError(txtNumeroRemito) == "") & (errorProvider1.GetError(cboProveedor) == "")) //si no tiene errores de tipeo, se mira si ya no se ingreso el remito
                {
                    //(ACA)remitosTa.FillByNroRemitoyProveedor(centerQuimDs.Remitos, txtNumeroRemito.Text, obtenerCodProveedor());

                    if (centerQuimDs.Remitos.Rows.Count != 0)
                    {
                        errorProvider1.SetError(txtNumeroRemito, "El remito especificado ya ha sido ingresado para el proveedor. \n\n Reinicie la interfaz para solucionar este problema.");


                    }
                    else
                    {
                        errorProvider1.SetError(txtNumeroRemito, "");

                    }


                }

            }
        }

        private void validarTurno()
        {
            if (cboTurno.Text.Trim() == "")
            {
                errorProvider1.SetError(cboTurno, "Turno: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(cboTurno, "");
            }
        }

        private void validarGrilla() //recorre todo el dataGride y verifica que los datos se encuentren correctos, si alguno está incorrecto los pinta de blanco
        {
            bool grillaSinError = true;  //inicializa el booleano que controla si el dgvProductos tiene al menos un error.

            foreach (DataGridViewRow row in dgvProductos.Rows)
            {

                string tipo = Convert.ToString(row.Cells[1].Value).Substring(0, 1);  //obtiene si el tipo de producto en la fila, en base a la primera letra de la descripción

                if (tipo == "T" || (tipo == "D"))
                {
                    if ((new ValidarDatos().ValidarNaturalesPositivos("Fila:", Convert.ToString(row.Cells[2].Value).Trim())) == "") //No tiene error. El producto terminado o disuelto por cantidad.
                    {
                        row.Cells[2].Style.BackColor = Color.White;

                    }
                    else      //con error en producto terminado o disuelto por cantidad
                    {
                        row.Cells[2].Style.BackColor = Color.LightPink;

                        grillaSinError = false;
                    }

                }
                else
                {
                    if ((new ValidarDatos().validarRealesPositvosSinCero("Fila:", Convert.ToString(row.Cells[2].Value).Trim())) == "") //No tiene error. El producto base.
                    {
                        row.Cells[2].Style.BackColor = Color.White;

                    }
                    else  //con error en producto base
                    {
                        row.Cells[2].Style.BackColor = Color.LightPink;

                        grillaSinError = false;
                    }
                }

            }


            if (grillaSinError)
            {
                errorProvider1.SetError(dgvProductos, "");
            }
            else
            {
                errorProvider1.SetError(dgvProductos, "Algunos de los campos cantidad en la grilla no contiene datos válidos.");
            }

            if (dgvProductos.RowCount == 0)
            {
                errorProvider1.SetError(dgvProductos, "La grilla no contiene productos.");
            }

        }

        private int obtenerCodUsuarioActual()  //Dato necesario para la apertura de una caja
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getCodUsuario();
        }


        private string obtenerNombreUsuarioActual()  //Dato necesario para la apertura de una caja
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getNombreUsuario();
        }


        private string obtenerFechaActual()  //Dato necesario para la apertura de una caja.
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }

        private void agregarIngreso()
        {
            ingresoMercaderiaTa.InsertQueryIngresoMercaderia(txtNumeroRemito.Text, obtenerCodProveedor(), this.dtpFecha.Value, this.cboTurno.SelectedItem.ToString(), obtenerCodUsuarioActual());

        }

        private int obtenerCodProveedor()  //obtiene el codigo de proveedor seleccionado en el combo.
        {
            proveedoresTa.FillByRazon(proveedoresDs.Proveedores, cboProveedor.SelectedItem.ToString());

            return proveedoresDs.Proveedores[0].codProveedor;
        }

        private void agregarProductoXIngreso() //agrega un registro a la tabla ProductosXremito
        {


            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                productoxIngresoTa.InsertQueryProductosxIngresoMercaderias(txtNumeroRemito.Text, row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString(), Convert.ToDecimal(row.Cells[2].Value));
                movimientoProductoRecibidos(row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString(), Convert.ToDecimal(row.Cells[2].Value), txtNumeroRemito.Text);

            }

        }

        private void incrementarStockProductos() //Actualiza la base de datos productos, incrementando su stock
        {

            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                productosTa.FillByNombre(centerQuimDs.Productos, row.Cells[1].Value.ToString());

                productosTa.UpdateQueryStockProducto(Convert.ToDecimal(centerQuimDs.Productos[0].stockActual) + Convert.ToDecimal(row.Cells[2].Value), centerQuimDs.Productos[0].descripcion, centerQuimDs.Productos[0].codProducto);

            }

        }

        private void movimientoProductoRecibidos(string codigo, string nombre, decimal cantidad, string ultimo)
        {
            movimientosTa.InsertQueryMovimientosxProducto(codigo, nombre, Convert.ToDateTime(dtpFecha.Value.ToString("d")), "A", "Ingreso Remito Nº: " + ultimo, cantidad);
        }

        
        
    }
}
